package com.henry.intercept;

import cn.hutool.core.util.ObjectUtil;
import com.henry.annotations.CryptHandlerClass;
import com.henry.annotations.DecryptFiled;
import com.henry.config.EncryptorConfig;
import com.henry.encryptor.Encryptor;
import com.henry.factory.EncryptorFactory;
import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.List;
import java.util.Properties;
import lombok.AllArgsConstructor;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

/**
 * 查询解密拦截器处理
 *
 * @author Liu Hanlin
 * @create 2025-08-21 23:56
 */
@Component
@Intercepts(
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class })
)
@AllArgsConstructor
public class DecryptFiledInterceptor implements Interceptor {

    private final EncryptorFactory encryptorFactory;

    private final EncryptorConfig encryptorConfig;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        // 获取 sql 执行查询后的结果集
        List<?> resultList = (List<?>) invocation.proceed();

        for (Object result : resultList){
            Class<?> resultType = result.getClass();
            if(ObjectUtil.isNull(resultType.getAnnotation(CryptHandlerClass.class))){
                break;
            }

            Field[] fields = resultType.getDeclaredFields();
            for (Field field : fields){
                field.setAccessible(true);
                if(ObjectUtil.isNotNull(field.getAnnotation(DecryptFiled.class))){
                    String fieldSourceValue = field.get(result).toString();
                    Encryptor encryptor = encryptorFactory.getEncryptor(encryptorConfig.getType());
                    if(ObjectUtil.isNull(encryptor)){
                        throw new RuntimeException("解密工具类型不存在，请检查配置！");
                    }
                    String fieldDecryptValue = encryptor.decrypt(fieldSourceValue, encryptorConfig.getValue());
                    field.set(result, fieldDecryptValue);
                }

            }

        }

        return resultList;
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
